package logo

import (
	"fmt"
	"runtime"
	"time"
)

type ProxyLogger struct {
	*logger
	entry Entry
}

const callDepth = 2

// func (e *ProxyLogger) WithData(data interface{}) *ProxyLogger {
// 	e.entry.Data = data
// 	return e
// }
func (e *ProxyLogger) With(data interface{}) *ProxyLogger {
	err, ok := data.(error)
	if ok {
		e.entry.Err = err
	} else {
		e.entry.Data = data
	}
	return e
}

// func (e *ProxyLogger) WithError(err error, hideCallStacks ...bool) *ProxyLogger {
// 	e.entry.Err = err
// 	if len(hideCallStacks) > 0 {
// 		e.entry.hideCallStacks = hideCallStacks[0]
// 	} else {
// 		e.entry.hideCallStacks = false
// 	}
// 	return e
// }

func (e *ProxyLogger) resetDataAndError() *ProxyLogger {
	e.entry.Data = nil
	e.entry.Err = nil
	return e
}

func (e *ProxyLogger) log(level LogLevel, callDepth int, v ...interface{}) {
	e.entry.Level = level
	e.entry.Time.Time = time.Now()
	e.entry.Message = fmt.Sprint(v...)

	if e.IsLogFileLine() {
		var ok bool
		_, e.entry.File, e.entry.Line, ok = runtime.Caller(callDepth)
		if !ok {
			e.entry.File = "???"
			e.entry.Line = 0
		}
	}

	fmt := e.logger.fmt // .GetFormatter()
	printer := e.logger.printers[level]
	msg, err := fmt(&e.entry)
	if err != nil {
		e.With(err).Error("log format error")
		return
	}
	printer.Print(msg)
}

func (e *ProxyLogger) logf(level LogLevel, callDepth int, format string, v ...interface{}) {
	e.entry.Level = level
	e.entry.Time.Time = time.Now()
	e.entry.Message = fmt.Sprintf(format, v...)

	if e.IsLogFileLine() {
		var ok bool
		_, e.entry.File, e.entry.Line, ok = runtime.Caller(callDepth)
		if !ok {
			e.entry.File = "???"
			e.entry.Line = 0
		}
	}

	fmt := e.logger.fmt // GetFormatter()
	printer := e.logger.printers[level]
	msg, err := fmt(&e.entry)
	if err != nil {
		e.With(err).Error("log format error")
		return
	}
	printer.Print(msg)
}

func (e *ProxyLogger) Debug(v ...interface{}) {
	e.log(LevelDebug, callDepth, v...)
}

func (e *ProxyLogger) Debugf(format string, v ...interface{}) {
	e.logf(LevelDebug, callDepth, format, v...)
}

func (e *ProxyLogger) Info(v ...interface{}) {
	e.log(LevelInfo, callDepth, v...)
}

func (e *ProxyLogger) Infof(format string, v ...interface{}) {
	e.logf(LevelInfo, callDepth, format, v...)
}

func (e *ProxyLogger) Warn(v ...interface{}) {
	e.log(LevelWarn, callDepth, v...)
}

func (e *ProxyLogger) Warnf(format string, v ...interface{}) {
	e.logf(LevelWarn, callDepth, format, v...)
}

func (e *ProxyLogger) Error(v ...interface{}) {
	e.log(LevelError, callDepth, v...)
}

func (e *ProxyLogger) Errorf(format string, v ...interface{}) {
	e.logf(LevelError, callDepth, format, v...)
}
